package com.likou.written.tongcheng;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Author: 陈桂明
 * Date: 2025/10/16 19:27
 * Description: tongcheng2
 */
public class tongcheng2 {

    class DLinkedNode {
        int key;
        int value;
        DLinkedNode pre;
        DLinkedNode next;

        public DLinkedNode() {

        }

        public DLinkedNode(int key, int value) {
            this.key = key;
            this.value = value;
        }
    }

    /**
     * 代码中的类名、方法名、参数名已经指定，请勿修改，直接返回方法规定的值即可
     * <p>
     * 可以假设输入都是符合规范的格式，完成核心逻辑代码即可
     *
     * @param ops   string字符串一维数组 操作符
     * @param datas int整型二维数组 数据
     * @return int整型ArrayList
     */
    private final Map<Integer, DLinkedNode> map = new HashMap<>();
    private int size;
    private int num;
    private DLinkedNode head;
    private DLinkedNode tail;

    public ArrayList<Integer> LRUCache(String[] ops, int[][] datas) {
        // write code here
        this.size = 0;
        this.num = datas[0][0];
        head = new DLinkedNode();
        tail = new DLinkedNode();
        head.next = tail;
        tail.pre = head;

        int index = 0;
        ArrayList<Integer> ans = new ArrayList<>();
        for (String op : ops) {
            if (op.equals("LRUCache")) {
                index++;
                ans.add(-2);
                continue;
            } else if (op.equals("put")) {
                put(datas[index][0], datas[index][1]);
                ans.add(-2);
                index++;
            } else {
                int v = get(datas[index][0]);
                ans.add(v);
                index++;
            }

        }

        return ans;
    }

    public int get(int key) {
        DLinkedNode dLinkedNode = map.get(key);
        if (dLinkedNode == null) {
            return -1;
        }
        moveToHead(dLinkedNode);

        return dLinkedNode.value;
    }

    public void put(int key, int value) {
        DLinkedNode dLinkedNode = map.get(key);
        if (dLinkedNode == null) {
            DLinkedNode dLinkedNode1 = new DLinkedNode(key, value);
            map.put(key, dLinkedNode1);
            addToHead(dLinkedNode1);
            size++;
            if (size > num) {
                DLinkedNode tail = removeTail();
                map.remove(tail.key);
                size--;
            }
        } else {
            dLinkedNode.value = value;
            moveToHead(dLinkedNode);
        }

    }


    private void addToHead(DLinkedNode node) {
        node.pre = head;
        node.next = head.next;
        head.next.pre = node;
        head.next = node;
    }

    private void removeNode(DLinkedNode node) {
        node.pre.next = node.next;
        node.next.pre = node.pre;
    }

    private void moveToHead(DLinkedNode node) {
        removeNode(node);
        addToHead(node);
    }

    private DLinkedNode removeTail() {
        DLinkedNode res = tail.pre;
        removeNode(res);

        return res;
    }

}
